package pl.darbat.incomecalc.math;

import java.io.FileNotFoundException;

import pl.darbat.incomecalc.Debug;
import pl.darbat.incomecalc.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

public class TaxCounter {

	private static final String TAG = "TaxCounter";
	
	//private boolean mIsValueLoaded = false;
	
	private ReverseTaxCounter mReverseTaxCounter;
	
	private int mStoredCurrentMonth;
	private double mStoredIncomeBruttoMonths;
	private double mStoredIncomeBaseMonths;
	
	private double mPercentZusPension = 0.0976;
	private double mPercentZusAllowance = 0.015;
	private double mPercentZusDisease = 0.0245;
	
	private double mPercentHealth = 0.09;
	private double mPercentHealthForAdvancePayment = 0.0775;
	
	private double mObtainCostPerMonth = 111.25;
	private double mObtainCostPerMonthHigh = 139.06;
	private double mTaxFreePerMonth = 46.33;
	
	private double mIncomeZUSMax = 94380;
	private double mIncomeTaxSecond = 85528;
	
	private double mTaxFirstThreshold = 0.18;
	private double mTaxSecondThreshold = 0.32;
	
	private int mCurrentMonth;

	private double mIncomeBrutto;
	private double mIncomeBruttoMonths;
	private double mIncomeNetto;

	private double mIncomeBaseMonths;
	
	private double mTaxZusPension;
	private double mTaxZusAllowance;
	private double mTaxZusDisease;
	private double mTaxZusSum;
	
	private double mTaxHealth;
	
	private double mTaxIncome;
	
	private int mTaxAdvancePayment;

	private Context mContext;
	
	private String mObtainCostPref;
	private String mTaxYear;
	private int mRoyaltyPercent;
	
	private SharedPreferences mSharedPrefs;
	
	//private double mTaxZusEmployer;
	//private double mFPEmployer;
	
	public TaxCounter(Context context){
		mContext = context;
		mReverseTaxCounter = new ReverseTaxCounter(mContext);
	}
	
	private void loadValues(Context context) throws FileNotFoundException {
		if(Debug.TAXCOUNTER) Log.v(TAG, "loadValues");
		
		mContext = context;
		
		mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
		mObtainCostPref = mSharedPrefs.getString("obtain_cost_per_month", "Normalny");
		mRoyaltyPercent = mSharedPrefs.getInt("royalty_percent2", 0);
		mTaxYear = mSharedPrefs.getString("year", "2011");
		CharSequence[] taxValues;
		if(mTaxYear.equalsIgnoreCase("2009")){         
			taxValues = mContext.getResources().getTextArray(R.array.values2009);
		}else if(mTaxYear.equalsIgnoreCase("2010")){
			taxValues = mContext.getResources().getTextArray(R.array.values2010);
		}else if(mTaxYear.equalsIgnoreCase("2011")){
			taxValues = mContext.getResources().getTextArray(R.array.values2011);
		}else if(mTaxYear.equalsIgnoreCase("2012")){
			taxValues = mContext.getResources().getTextArray(R.array.values2012);
		}else{
			throw new FileNotFoundException();
		}
		
		
		mPercentZusPension = Double.parseDouble(taxValues[0].toString());
		mPercentZusAllowance = Double.parseDouble(taxValues[1].toString());
		mPercentZusDisease = Double.parseDouble(taxValues[2].toString());
		
		mPercentHealth = Double.parseDouble(taxValues[3].toString());
		mPercentHealthForAdvancePayment = Double.parseDouble(taxValues[4].toString());
		
		mObtainCostPerMonth = Double.parseDouble(taxValues[5].toString());
		mObtainCostPerMonthHigh = Double.parseDouble(taxValues[6].toString());
		mTaxFreePerMonth = Double.parseDouble(taxValues[7].toString());
		
		mIncomeZUSMax = Double.parseDouble(taxValues[8].toString());
		mIncomeTaxSecond = Double.parseDouble(taxValues[9].toString());
		
		mTaxFirstThreshold = Double.parseDouble(taxValues[10].toString());
		mTaxSecondThreshold = Double.parseDouble(taxValues[11].toString());
		
//		if(Debug.TAXCOUNTER){
//			Log.v(TAG, 	" " + mPercentZusPension + 
//						"; " + mPercentZusAllowance +
//						"; " + mPercentZusDisease +
//						"; " + mPercentHealth +
//						"; " + mPercentHealthForAdvancePayment +
//						"; " + mObtainCostPerMonth +
//						"; " + mObtainCostPerMonthHigh +
//						"; " + mTaxFreePerMonth +
//						"; " + mIncomeZUSMax +
//						"; " + mIncomeTaxSecond +
//						"; " + mTaxFirstThreshold +
//						"; " + mTaxSecondThreshold);
//		}
		

	}
	
	// Count Netto from Brutto:
	private double countTaxZusPension(double income){
		if(mIncomeBruttoMonths > mIncomeZUSMax){
			if((mIncomeBruttoMonths-mIncomeBrutto) <  mIncomeZUSMax){
				return checkPositiveAndRoundToTwoDigits((mIncomeZUSMax-(mIncomeBruttoMonths-mIncomeBrutto))* mPercentZusPension);
			}else{
				return 0;
			}
		} else {
			return checkPositiveAndRoundToTwoDigits(income * mPercentZusPension);
		}
	}
	
	private double countTaxZusAllowance(double income){
		if(mIncomeBruttoMonths > mIncomeZUSMax){
			if((mIncomeBruttoMonths-mIncomeBrutto) <  mIncomeZUSMax){
				return checkPositiveAndRoundToTwoDigits((mIncomeZUSMax-(mIncomeBruttoMonths-mIncomeBrutto))* mPercentZusAllowance);
			}else{
				return 0;
			}
		} else {
			return checkPositiveAndRoundToTwoDigits(income * mPercentZusAllowance);
		}
	}
	
	private double countTaxZusDisease(double income){
		return checkPositiveAndRoundToTwoDigits(income * mPercentZusDisease);
	}
	
	private double countTaxZusSum(double income){
		mTaxZusPension = countTaxZusPension(income);
		mTaxZusAllowance = countTaxZusAllowance(income);
		mTaxZusDisease = countTaxZusDisease(income);

		return checkPositiveAndRoundToTwoDigits(mTaxZusPension + mTaxZusAllowance + mTaxZusDisease);
	}
	
	private double countTaxHealth(double incomeMinusZus){
		return checkPositiveAndRoundToTwoDigits(incomeMinusZus * mPercentHealth);
	}
	
	private double countTaxIncome(double incomeMinusCost){
		double royaltyPercent = mRoyaltyPercent / 100D;
		double noRoyaltyPercent = 1 - royaltyPercent;
		if(mIncomeBaseMonths > mIncomeTaxSecond){
			if((mIncomeBaseMonths-mIncomeBrutto) <  mIncomeTaxSecond){
				return checkPositiveAndRoundToTwoDigits((royaltyPercent * incomeMinusCost * mTaxFirstThreshold * 0.5) + (noRoyaltyPercent * incomeMinusCost * mTaxFirstThreshold)- mTaxFreePerMonth); 
				//return checkPositiveAndRoundToTwoDigits((incomeMinusCost * mTaxFirstThreshold) - mTaxFreePerMonth);
			}else{
				return checkPositiveAndRoundToTwoDigits((royaltyPercent * incomeMinusCost * mTaxSecondThreshold * 0.5) + (noRoyaltyPercent * incomeMinusCost * mTaxSecondThreshold)- mTaxFreePerMonth); 
				//return checkPositiveAndRoundToTwoDigits((incomeMinusCost * mTaxSecondThreshold) - mTaxFreePerMonth);
			}
		} else {
			return checkPositiveAndRoundToTwoDigits((royaltyPercent * incomeMinusCost * mTaxFirstThreshold * 0.5) + (noRoyaltyPercent * incomeMinusCost * mTaxFirstThreshold)- mTaxFreePerMonth); 
			//return checkPositiveAndRoundToTwoDigits((incomeMinusCost * mTaxFirstThreshold) - mTaxFreePerMonth);
		}
	}
	
	private double countTaxHealthForAdvancePayment(double incomeMinusZus){
		return checkPositiveAndRoundToTwoDigits(incomeMinusZus * mPercentHealthForAdvancePayment);
	}

	private int countTaxAdvancePayment(double incomeMinusZus){
		double taxHealthForAdvancePayment = countTaxHealthForAdvancePayment(incomeMinusZus);
		//Log.v(TAG,"taxHealthForAdvancePayment: " + taxHealthForAdvancePayment);
		mTaxAdvancePayment = checkPositiveAndRound((mTaxIncome - taxHealthForAdvancePayment));
		
		return mTaxAdvancePayment;
	}

	public double countIncomeNetto(double incomeBrutto, boolean argumentEstimation){
		if(Debug.TAXCOUNTER) Log.v(TAG, "countIncomeNetto: " + incomeBrutto);
		try {
			loadValues(mContext);
		} catch (FileNotFoundException e) {
			throw new InternalError();
		}
		if(argumentEstimation){
			mStoredCurrentMonth = mCurrentMonth;
			mStoredIncomeBruttoMonths = mIncomeBruttoMonths;
			mStoredIncomeBaseMonths = mIncomeBaseMonths;
		}

		mIncomeBruttoMonths += incomeBrutto;
		mCurrentMonth += 1;
		if (mCurrentMonth > 12) {
			throw new IllegalStateException("Month number is over 12");
		}
		
		mIncomeBrutto = incomeBrutto;
		if(Debug.TAXCOUNTER) Log.v(TAG,"IncomeBrutto: " + mIncomeBrutto);
		mTaxZusSum = countTaxZusSum(mIncomeBrutto);
		if(Debug.TAXCOUNTER) Log.v(TAG,"TaxZusSum: " + mTaxZusSum);
		double incomeMinusZus = checkPositiveAndRoundToTwoDigits(mIncomeBrutto - mTaxZusSum);
		if(Debug.TAXCOUNTER) Log.v(TAG,"incomeMinusZus: " + incomeMinusZus);		
		mTaxHealth = countTaxHealth(incomeMinusZus);
		if(Debug.TAXCOUNTER) Log.v(TAG,"TaxHealth: " + mTaxHealth);
		double incomeMinusCost;
		if(mObtainCostPref.equals("Podwyzszony")){
			incomeMinusCost = Math.round(incomeMinusZus - mObtainCostPerMonthHigh);
		} else {
			incomeMinusCost = Math.round(incomeMinusZus - mObtainCostPerMonth);
		}
		mIncomeBaseMonths += incomeMinusCost;
		if(Debug.TAXCOUNTER) Log.v(TAG,"incomeMinusCost: " + incomeMinusCost);
		mTaxIncome = countTaxIncome(incomeMinusCost);
		if(Debug.TAXCOUNTER) Log.v(TAG,"TaxIncome: " + mTaxIncome);
		mTaxAdvancePayment = countTaxAdvancePayment(incomeMinusZus);
		if(Debug.TAXCOUNTER) Log.v(TAG,"TaxAdvancePayment: " + mTaxAdvancePayment);
		if(mTaxHealth > mTaxIncome) {
			Log.v(TAG, "Health Tax bigger than Income Tax, clliping...");
			mTaxHealth = mTaxIncome;
			if(Debug.TAXCOUNTER) Log.v(TAG,"New TaxHealth: " + mTaxHealth);
		}
		mIncomeNetto = checkPositiveAndRoundToTwoDigits(mIncomeBrutto - (mTaxZusSum + mTaxHealth + mTaxAdvancePayment));
		if(Debug.TAXCOUNTER) Log.v(TAG,"mIncomeNetto: " + mIncomeNetto);
		
		if(argumentEstimation){
			
			clearForEstimate();
		}

		return mIncomeNetto;
	}
	
	private void clearForEstimate(){
		
		mCurrentMonth = mStoredCurrentMonth;
		mIncomeBruttoMonths = mStoredIncomeBruttoMonths;
		mIncomeBaseMonths = mStoredIncomeBaseMonths;

	}
	
	// Count Brutto from Netto:
	
	public double countIncomeBrutto(double incomeNetto){
		
		double incomeBrutto = checkPositiveAndRoundToTwoDigits(mReverseTaxCounter.estimateIncomeBrutto(this, incomeNetto));
		countIncomeNetto(incomeBrutto, false);
		
		return incomeBrutto;
	}
	
	// Math:

	public static double rountToTwoDigits(double input) {
		//Log.v(TAG,"i: " + input + ", rounded: " + (double)(Math.round(input*100))/100);
		return (double)(Math.round(input*100))/100;
	}
	
	public static double checkPositiveAndRoundToTwoDigits(double input) {
		if(input > 0){
			return rountToTwoDigits(input);
			//return new BigDecimal(input).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
		} else {
			return 0;
		}
	}
	
	public static String roundToTwoDigitsString(double input) {
		return Double.toString(rountToTwoDigits(input));
		//return new BigDecimal(input).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
	}
	
	public static int checkPositiveAndRound(double input) {
		if(input > 0){
			return (int) Math.round(input);
		} else {
			return 0;
		}
	}
	
	// Getters:
	
	public double getIncomeBrutto() {
		return mIncomeBrutto;
	}
	
	public double getIncomeNetto() {
		return mIncomeNetto;
	}
	
	public double getTaxZusPension() {
		return mTaxZusPension;
	}
	
	public double getTaxZusAllowance() {
		return mTaxZusAllowance;
	}
	
	public double getTaxZusDisease() {
		return mTaxZusDisease;
	}
	
	public double getTaxZusSum() {
		return mTaxZusSum;
	}
	
	public double getTaxHealth() {
		return mTaxHealth;
	}
	
	public double getTaxAdvancePayment() {
		return mTaxAdvancePayment;
	}

	public String getObtainCostPref() {
		return mObtainCostPref;
	}

	public String getTaxYear() {
		return mTaxYear;
	}

	public int getRoyaltyPercent() {
		return mRoyaltyPercent;
	}
	
}
